React状態管理ライブラリ Zustandのミドルウェアを使ってみた
こんにちは。データアナリティクス事業本部 サービスソリューション部の北川です。
Zustandとは
ZustandはReactの状態管理ライブラリの一つです。シンプルで使いやすく、他の状態管理ライブラリと比べてもコード量が少ないです。
基本的な使い方については、以下のエントリで書いています。
今回は、Zustandのミドルウェアを使ってみました。基本的には、公式のGitHubに沿って進めています。
Next.jsプロジェクトを作成
前回、エントリで使用したコードをそのまま使っていきます。
$ npx create-next-app sample-zustand --ts
$ yarn add zustand // または $ npm install zustand
import create from "zustand"; type Count = { count: number; increaseCount: () => void; resetCount: () => void; } export const useStore = create<Count>((set) => ({ count: 0, increaseCount: () => set((state) => { return { count: state.count + 1 }; }), resetCount: () => set({ count: 0 }), }));
import type { NextPage } from "next"; import { useStore } from "../libs/store"; import styles from "../styles/Home.module.css"; const Count = () => { const count = useStore((state) => state.count); console.log(count); return ( <> <h2>count: {count}</h2> </> ); }; const IncreaseCountButton = () => { const increaseCount = useStore((state) => state.increaseCount); return <button onClick={() => increaseCount()}>Increase</button>; }; const ResetButton = () => { const { resetCount } = useStore(); return <button onClick={() => resetCount()}>Reset</button>; }; const Home: NextPage = () => { return ( <div className={styles.container}> <main className={styles.main}> <Count /> <IncreaseCountButton /> <ResetButton /> </main> </div> ); }; export default Home;
ミドルウェアを試してみる
Zustandが用意しているいくつかのミドルウェアは、"zustand/middleware"
からインポートすることで使用できます。
devTools
devToolsミドルウェアを使用すると、拡張機能のRedux DevToolsを使えるようになります。 Redux DevToolsに関しては、こちらのエントリで書いています。
set
の第3引数に、それぞれのactionTypeを渡すことができます。
import create from "zustand"; import { devtools } from "zustand/middleware"; type Count = { count: number; increaseCount: () => void; resetCount: () => void; }; export const useStore = create<Count>()( devtools((set) => ({ count: 0, increaseCount: () => set( (state: { count: number }) => { return { count: state.count + 1 }; }, false, "increaseCount" ), resetCount: () => set({ count: 0 }, false, "resetCount"), })) );
immer
immerはオブジェクトをイミュータブルに扱うためのライブラリになります。
developersIOでも、以下のエントリが投稿されています。
immerミドルウェアを使用すると、push()やunshift()などの破壊的なメソッドを使用したstateの変更ができるようになります。このミドルウェアは、"zustand/middleware/immer"
からインストールします。
こちらは、公式のimmerミドルウェアを使ったコードです。
import create from 'zustand' import { immer } from 'zustand/middleware/immer' const useBeeStore = create( immer((set) => ({ bees: 0, addBees: (by) => set((state) => { state.bees += by }), })) )
自作ミドルウェア
提供されているミドルウェアではなく、自作のミドルウェアも作成できます。Zustandのデモでは、stateの変更を記録し、ログとして出力するミドルウェアを定義しています。
import create from "zustand"; type Count = { count: number; increaseCount: () => void; resetCount: () => void; }; const log = (config) => (set, get, api) => config( (...args) => { console.log(" applying", args); set(...args); console.log(" new state", get()); }, get, api ); export const useStore = create<Count>()( log((set) => ({ count: 0, increaseCount: () => set((state: { count: number }) => { return { count: state.count + 1 }; }), resetCount: () => set({ count: 0 }), })) );
複数ミドルウェアを使う
もちろん、以下のように記述することで、複数のミドルウェアを使用できます。
export const useStore = create<Count>()( log( devtools((set) => ({ count: 0, increaseCount: () => set( (state: { count: number }) => { return { count: state.count++ }; }, false, "increaseCount" ), resetCount: () => set({ count: 0 }, false, "resetCount"), })) ) );
まとめ
今回は、Zustandのミドルウェアを簡単にですが、試してみました。Zustaindでは他にも、再現が難しかったのですが、stateの状態を保持するPersistミドルウェアなどもあります。
ミドルウェアは学ぶことが多くまだまだ勉強中です。これからもインプット、アウトプットに力を入れていきたいと思います。
ではまた。